import React, { Component, createContext } from 'react';

const { Provider, Consumer } = createContext();
const withScope = (WrappedComponent) => (props) => <Consumer>{(keep) => <WrappedComponent {...props} keep={keep} />}</Consumer>;

export class AliveScope extends Component {
  nodes = {};
  state = {};

  keep = (id, children, props) =>
    new Promise((resolve) =>
      this.setState(
        {
          [id]: {
            id,
            children: React.Children.map(props.children, (child) => {
              // console.log(path);
              // console.log(props);
              return React.cloneElement(child, {
                router: props.router,
              });
            }),
          },
        },
        () => {
          resolve(this.nodes[id]);
        }
      )
    );

  render() {
    return (
      <Provider value={this.keep}>
        {this.props.children}
        {Object.values(this.state).map(({ id, children }) => (
          <div
            key={id}
            ref={(node) => {
              this.nodes[id] = node;
            }}
          >
            {children}
          </div>
        ))}
      </Provider>
    );
  }
}

class KeepAlive extends Component {
  init = async ({ id, children, keep }) => {
    const realContent = await keep(id, children, this.props);
    if (this.placeholder) {
      // console.log(realContent);
      // console.log(realContent.children[0]);
      this.scope = realContent;
      this.c = realContent.children[0];
      // this.placeholder.parentNode.appendChild(realContent.children[0]);

      this.placeholder.parentNode.replaceChild(this.c, this.placeholder);
      // this.placeholder.appendChild(realContent);
    }
  };
  componentDidMount() {
    this.init(this.props);
  }
  componentWillUnmount() {
    if (this.c) {
      this.c.parentNode.replaceChild(this.placeholder, this.c);
      this.scope.appendChild(this.c);
      this.placeholder.appendChild(this.scope);
    }

    // this.scope.appendChild(this.placeholder.children[0]);
  }

  render() {
    return <div ref={(a) => (this.placeholder = a)}></div>;
  }
}

export default withScope(KeepAlive);
